import * as THREE from "three"
import { OrbitControls } from "three/addons/Addons.js";
import { CSS3DObject, CSS3DRenderer, CSS2DRenderer, CSS2DObject } from "three/addons/Addons.js";


var camera, root, scene, renderer, renderer2, renderer3, background;
var sphere;
var light

var controls

var css3ds = []

init();
animate(performance.now());

function init() {
    scene = new THREE.Scene()
    root = new THREE.Object3D()

    scene.add(root)

    const axesHelper = new THREE.AxesHelper(100)
    scene.add(axesHelper)

    background = makeElementObject("div", 100, 100)
    background.css3dObject.element.textContent = "I am a <div> element "
    background.css3dObject.element.setAttribute('contenteditable', '')
    background.css3dObject.element.style.opacity = "1"
    background.css3dObject.element.style.padding = '10px'
    const color1 = '#7bb38d'
    const color2 = '#71a381'
    background.css3dObject.element.style.background = `repeating-linear-gradient(
        45deg,
        ${color1},
        ${color1} 10px,
        ${color2} 10px,
        ${color2} 20px
    )`
    root.add(background);

    const button = makeElementObject('button', 75, 20)
    button.css3dObject.element.style.border = '2px solid #fa5a85'
    button.css3dObject.element.textContent = "Click me!"
    button.css3dObject.element.addEventListener('click', () => alert('You clicked a <button> element in the DOM!'))
    button.position.z = 10
    button.css3dObject.element.style.background = '#e64e77'
    background.add(button)

    // const element = document.createElement('div')
    // element.style.width = "50px"
    // element.style.height = "50px"
    // element.innerText = "我是CSS2D对象"
    // element.style.background = `repeating-linear-gradient(
    //     45deg,
    //     ${color1},
    //     ${color1} 10px,
    //     ${color2} 10px,
    //     ${color2} 20px
    // )`
    // const css2d = new CSS2DObject(element)
    // css2d.position.x = 55
    // root.add(css2d)

    // make a geometry that we will clip with the DOM elememt.
    ~function () {
        var material = new THREE.MeshPhongMaterial({
            color: 0x991d65,
            emissive: 0x000000,
            specular: 0x111111,
            side: THREE.DoubleSide,
            flatShading: false,
            shininess: 30,
            vertexColors: true,
        })

        var geometry = new THREE.SphereGeometry(70, 32, 32);

        // give the geometry custom colors for each vertex {{
        geometry = geometry.toNonIndexed(); // ensure each face has unique vertices

        const position = geometry.getAttribute("position");
        var colors = [];

        const color = new THREE.Color
        for (var i = 0, l = position.count; i < l; i++) {
            color.setHSL(Math.random() * 0.2 + 0.5, 0.75, Math.random() * 0.15 + 0.85);
            colors.push(color.r, color.g, color.b);
        }

        geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
        // }}

        sphere = new THREE.Mesh(geometry, material);
        sphere.position.z = 20;
        sphere.position.y = -100;
        sphere.castShadow = true;
        sphere.receiveShadow = false;
        root.add(sphere);
    }()

    // light
    ~function () {
        var ambientLight = new THREE.AmbientLight(0x999999, 1.5);
        root.add(ambientLight);

        light = new THREE.PointLight(0xffffff, 1, 0);
        light.castShadow = true;
        light.position.z = 150;
        light.shadow.mapSize.width = 1024;  // default
        light.shadow.mapSize.height = 1024; // default
        light.shadow.camera.near = 1;       // default
        light.shadow.camera.far = 2000;      // default

        scene.add(new THREE.PointLightHelper(light, 10))

        root.add(light);
    }()

    camera = new THREE.PerspectiveCamera();
    camera.position.set(0, 0, 500);

    renderer2 = new CSS3DRenderer();
    renderer2.domElement.style.position = 'absolute';
    renderer2.domElement.style.top = 0;
    // renderer2.domElement.style.pointerEvents = "none"; // 禁用鼠标事件
    document.querySelector('#webgl').appendChild(renderer2.domElement);

    renderer3 = new CSS2DRenderer();
    renderer3.domElement.style.position = 'absolute';
    renderer3.domElement.style.top = 0;
    renderer3.domElement.style.pointerEvents = "none"; // 禁用鼠标事件
    document.querySelector('#webgl').appendChild(renderer3.domElement);


    renderer = new THREE.WebGLRenderer({ antialias: true });
    // renderer.setClearColor(0x000000, 0);
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.shadowMap.enabled = true;
    renderer.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap
    renderer.domElement.id = "webgl3d"

    document.querySelector('#webgl').appendChild(renderer.domElement);

    controls = new OrbitControls(camera, renderer.domElement)

    window.addEventListener('resize', resize)
    resize()
}

function resize() {
    camera.fov = 45
    camera.aspect = window.innerWidth / window.innerHeight
    camera.near = 1
    camera.far = 2000
    camera.updateProjectionMatrix()
    renderer2.setSize(window.innerWidth, window.innerHeight);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer3.setSize(window.innerWidth, window.innerHeight);
}

function animate(time) {

    light.position.x = 30 * Math.sin(time * 0.003) + 30;
    light.position.y = 40 * Math.cos(time * 0.001) - 20;
    background.rotation.y = Math.PI / 8 * Math.cos(time * 0.001) - Math.PI / 6;
    background.rotation.x = Math.PI / 10 * Math.sin(time * 0.001) - Math.PI / 10;
    sphere.rotation.x += 0.005
    sphere.rotation.y += 0.005

    scene.updateMatrixWorld()

    const direction = new THREE.Vector3().subVectors(camera.position, controls.target).normalize()

    css3ds.forEach(css3d => {
        const lookAt = css3d.getWorldPosition(new THREE.Vector3()).add(direction)
        css3d.lookAt(lookAt)
    })

    renderer.render(scene, camera);
    renderer2.render(scene, camera);
    // renderer3.render(scene, camera);
    controls.update()



    requestAnimationFrame(animate);
}


/**
 * 
 * @param { keyof HTMLElementTagNameMap} type 
 * @param {number} width 
 * @param {number} height 
 * @returns 
 */
function makeElementObject(type, width, height) {

    const obj = new THREE.Object3D()

    const element = document.createElement(type);
    element.style.width = width + 'px';
    element.style.height = height + 'px';
    element.style.opacity = 0.999;
    element.style.boxSizing = 'border-box'

    var css3dObject = new CSS3DObject(element);
    obj.css3dObject = css3dObject
    obj.add(css3dObject)


    // make an invisible plane for the DOM element to chop
    // clip a WebGL geometry with it.
    var material = new THREE.MeshPhongMaterial({
        opacity: 0.0001,
        color: new THREE.Color(0x111111),
        blending: THREE.NoBlending,
        // side : THREE.DoubleSide,
    });
    var geometry = new THREE.BoxGeometry(width, height, 1);
    var mesh = new THREE.Mesh(geometry, material);
    mesh.castShadow = true;
    mesh.receiveShadow = true;

    css3ds.push(css3dObject, mesh)

    obj.add(mesh);

    // mesh.visible = false

    return obj
}

controls.addEventListener("change", e => {

    css3ds.forEach(css3d => {

        if (!css3d.__distance) {

            css3d.__distance = camera.position.distanceTo(css3d.position)

        } else {
            const distance = camera.position.distanceTo(css3d.position)

            const scale = distance / css3d.__distance

            css3d.scale.set(scale, scale, scale)

        }

    })

})

setTimeout(() => console.log(background.css3dObject.element), 1000)